/** 
    @file pixelroom.hpp
    @brief Game room
*/

#ifndef PM3_PIXELROOM_HPP
#define PM3_PIXELROOM_HPP

#include "logger.hpp"
#include "pixelnode.hpp"
#include "pixelobj.hpp"
#include "portal_debug.hpp"

#include <OgreSceneNode.h>

//! A zone for hiding stuff e.g. Hammerspace
#define PM_HIDEZONE "HideZone"

namespace pm3 {
    //! Rendering modes for objects
    enum RENDER_MODE {
        //! Always hide the objects from being rendered
        RM_HIDE = 0,
        //! Use portal-connected-zones for visibility checks
        RM_PVS = 1,
        //! Always show the objects
        RM_SHOW = 2
    };

    /**
        @class PIXELROOM
        @brief Game object
    */
    class PIXELROOM: public PIXELNODE {
    friend class PIXELMAP;
    friend class PIXELLAYER;
    public:
            /**
                @brief Constructor
            */
            PIXELROOM();
            /**
                @brief Destructor
            */
            ~PIXELROOM();

            /**
                @brief Gets the position of the room in grid coordinates
                @return Position in grid coordinates
            */
            inline Ogre::Vector3 get_grid_pos() const {
                return m_grid_pos;
            }

            /**
                @brief Gets the value of a variable
                @param[in] r_var Reference to the name of the variable
                @return Variable value as string
            */
            std::string get_variable( const std::string &r_var );

            /**
                @brief Sets the value of a variable
                @param[in] r_var Reference to the name of the variable
                @param[in] r_val Reference to the value of the variable
            */
            void set_variable( const std::string &r_var, const std::string &r_val );

            /**
                @brief Gets a pointer to the zone the room is in
                @return Pointer to the zone
            */
            inline Ogre::PCZone *get_zone() const {
                return m_pvs_zone;
            }

            /**
                @brief Sets room rendering mode
                @param[in] e_rm Rendering mode
            */
            void set_render_mode( RENDER_MODE e_rm );

            /**
                @brief Gets room rendering mode
                @return Rendering mode
            */
            inline RENDER_MODE get_render_mode() const {
                return m_render_mode;
            }

            /**
                @brief Gets room name
                @return Room name
            */
            std::string get_name() const;

            /**
                @brief Shows or hides debug box
                @param[in] b_show To show or hide?
            */
            void show_debug_box( bool b_show );

            /**
                @brief Checks if debug box is shown
                @return True or false
            */
            inline bool debug_box_shown() const {
                return m_show_debug;
            }

    protected:
            /**
                @brief Unloads the pixel room
            */
            void unload();

            /**
                @brief Sets the position of the room in grid coordinates
            */
            inline void set_grid_pos( const Ogre::Vector3 &r_pos ) {
                m_grid_pos = r_pos;
            }

            /**
                @brief Initializes the room
                @param[in] f_size Room size
                @param[in] p_obj Pointer to the object
            */
            void init( Ogre::Real f_size, PIXELOBJ *p_obj );

            /**
                @brief Initializes portals
                @param[in] p_zone Pointer to the zone in which the room lies
            */
            void init_portals( Ogre::PCZone *p_zone );

            /**
                @brief Gets a pointer to a room portal that points in the requested direction
                @param[in] i_dir Direction of the portal to be requested
                @return Pointer to the requested portal
            */
            Ogre::Portal *get_portal( int i_dir ) const;

            /**
                @brief Removes a portal
                @param[in] i_dir Direction of the portal to be removed
            */
            void remove_portal( int i_dir );

            /**
                @brief Renders debug items
            */
            void debug_render();

            /**
                @brief Clears the portals
            */
            void clear_portals();

            /**
                @brief Sets debug box color
                @param[in] r_col Reference to the new color
                @return True on success, otherwise false
            */
            bool set_debug_box_color( const Ogre::ColourValue &r_col );

    private:
            //! The zone the room is in
            Ogre::PCZone *m_zone;
            //! The zone where the room has its portals
            Ogre::PCZone *m_pvs_zone;
            //! Room portals
            Ogre::Portal *m_portals [pm3::util::DID_LAST];

            //! Room rendering mode
            RENDER_MODE m_render_mode;

            //! Map room size
            Ogre::Real m_size;
            //! Room position (grid coordinates)
            Ogre::Vector3 m_grid_pos;

            //! Show debug box
            bool m_show_debug;
            //! Debug box entity
            Ogre::Entity *m_debug_box;
            //! Debug node
            Ogre::PCZSceneNode *m_debug_node;

            //! Room variables
            std::map<std::string, std::string> m_variables;

            /**
                @brief Updates the home zone for all room subnodes
            */
            void update_zone();
    };
}

#endif

